package client;

import java.util.Vector;

import server.Entity.EntityType;
import shared.Vec2f;
import shared.Vec2i;
import vmo.Actor;
import vmo.Actor_Player;
import vmo.Chunk;
import vmo.PlayerData;
import network.Client;
import network.Packet;
import network.Packet.packettype;
import network.Packet_Chunk;
import network.Packet_Player;
import network.Player;
import network.Request;

public class Main_Sim {

	Client m_client;
	Chunk [][] m_chunks;
	Vector <Actor> m_actors;
	float m_clock,m_maintick;
	
	int m_width,m_height;
	boolean m_world;
	
	public PlayerData m_player;
	
	public boolean m_buildview;
	
	public Main_Sim(Client client)
	{
		m_buildview=false;
//		m_pos=new Vec2f(24,24);
		m_clock=0;
		m_maintick=0;
		m_client=client;
		m_chunks=new Chunk[9][];
		for (int i=0;i<9;i++)
		{
			m_chunks[i]=new Chunk[9];

		}
		m_actors=new Vector<Actor>();
	}
	
	public void Update(float dt)
	{
		m_client.Update(dt);
		HandleRequests();		
		Packet p=m_client.getPacket();
		if (p!=null)
		{
			switch (p.getType())
			{
				case CHUNK:
					HandleRequests();			
				break;
				case PLAYER:
					HandlePlayer((Packet_Player)p);
				break;
				
			}

		}
		m_clock+=dt;
		if (m_clock>m_maintick-0.1F)
		{
			if (m_player!=null)
			{
				ChunkLoader();
	
			}
			m_maintick=m_clock;
		}
		if (m_actors.size()>0)
		{
			for (int i=0;i<m_actors.size();i++)
			{
				m_actors.get(i).Update(dt);
			}
		}
		
	}
	
	void HandlePlayer(Packet_Player p)
	{
		m_player=p.m_player;
		m_width=p.m_ewidth;
		m_height=p.m_eheight;
		if (p.m_Etype==EntityType.WORLD)
		{
			m_world=true;
		}
		else
		{
			m_world=false;
		}
		//m_actors.add(new Actor_Player(m_player));
	}
	
	void HandleRequests()
	{
		Request req=m_client.getCompleteRequest();
		if (req!=null)
		{
			//figure out which chunk on the grid we can use to store the new chunk
			int tx=(int) (m_player.m_pos.x/16);
			int ty=(int) (m_player.m_pos.y/16);
			int x=(int) (req.getX()-tx); int y=(int) (req.getY()-ty);
			x+=4; y+=4;
			if (x>=0 && x<9 && y>=0 && y<9)
			{
				if (m_chunks[x][y]==null)
				{
					m_chunks[x][y]=new Chunk(false);
					m_chunks[x][y].m_position=new Vec2i(req.getX(),req.getY());
				}
				for (int i=0;i<4;i++)
				{
					Packet_Chunk pack=(Packet_Chunk) req.getPacket(i);
					pack.ToChunk(m_chunks[x][y], req.getZ());
				}
			
				m_chunks[x][y].BatchsetImage();
				m_buildview=true;
			}

		}
	}
	
	void ChunkLoader()
	{
		int x=(int) (m_player.m_pos.x/16); int y=(int) (m_player.m_pos.y/16);
		

		
		//try to load all chunks around the player location
		for (int i=3;i<6;i++)
		{
			for (int j=3;j<6;j++)
			{
				if (y-4+j>=0 && y-4+j<m_height)
				{
					if (x-4+i>=0 && x-4+i<m_width)
					{
						if (m_chunks[i][j]==null)
						{
							//request chunk whole cloth
			
							m_client.TransmitRequest(x-4+i, y-4+j, m_player.m_layer, m_player.m_entity);
							
						}
						else
						{
							//check each layer individually
							if (m_chunks[i][j].m_tiles[m_player.m_layer]!=null)
							{
								if (m_player.m_layer>0)
								{
									if (m_chunks[i][j].m_tiles[m_player.m_layer-1]==null)
									{
										m_client.TransmitRequest(x-4+i, y-4+j, m_player.m_layer-1, m_player.m_entity);	
									}
									else if (m_player.m_layer>1)
									{
										if (m_chunks[i][j].m_tiles[m_player.m_layer-2]==null)
										{	
											m_client.TransmitRequest(x-4+i, y-4+j, m_player.m_layer-2, m_player.m_entity);	
										}	
									}
									
								}
							}
							else
							{
								m_client.TransmitRequest(x-4+i, y-4+j, m_player.m_layer, m_player.m_entity);	
								
							}
							
						}				
					
					}
					else if (m_world)
					{
						if (m_chunks[i][j]==null)
						{
							//request chunk whole cloth
			
							m_client.TransmitRequest(x-4+i, y-4+j, m_player.m_layer, m_player.m_entity);
							
						}
						else
						{
							//check each layer individually					
							if (m_chunks[i][j].m_tiles[m_player.m_layer]!=null)
							{
								if (m_player.m_layer>0)
								{
								m_client.TransmitRequest(x-4+i, y-4+j, m_player.m_layer-1, m_player.m_entity);	
									if (m_player.m_layer>1)
									{
										m_client.TransmitRequest(x-4+i, y-4+j, m_player.m_layer-2, m_player.m_entity);			
									}
								}
							}
							else
							{
								m_client.TransmitRequest(x-4+i, y-4+j, m_player.m_layer, m_player.m_entity);			
							}
							
						}								
					}
				}
				

			}
		}
	}
	
	boolean ShiftNeeded()
	{
		//finish writing this later
		if (m_chunks[4][4]!=null)
		{
			Vec2i p=m_chunks[4][4].m_position;
			int x=(int) (m_player.m_pos.x/16);
			int y=(int) (m_player.m_pos.y/16);
			if (p.x>x)
			{
				ShiftRight();
				return true;
			}
			if (p.x<x)
			{
				ShiftLeft();
				return true;	
			}
			if (p.y>y)
			{
				ShiftDown();
				return true;
			}
			if (p.y<y)
			{
				ShiftUp();
				return true;
			}
		}
		return false;
	}
	
	void ShiftLeft()
	{
		for (int i=1;i<9;i++)
		{
			m_chunks[i-1]=m_chunks[i];

		}
		m_chunks[8]=new Chunk[9];
	}
	
	void ShiftRight()
	{
		for (int i=7;i>=0;i--)
		{
			m_chunks[i+1]=m_chunks[i];

		}
		m_chunks[8]=new Chunk[9];		
	}
	
	void ShiftUp()
	{
		for (int i=0;i<9;i++)
		{
			for (int j=1;j<9;j++)
			{
				m_chunks[i][j-1]=m_chunks[i][j];
			}
			m_chunks[i][8]=null;
		}		
	}

	void ShiftDown()
	{
		for (int i=0;i<9;i++)
		{
			for (int j=7;j>=0;j--)
			{
				m_chunks[i][j+1]=m_chunks[i][j];
			}
			m_chunks[i][0]=null;
		}	
	}
	
	public void End()
	{
		m_client.Discard();
	}
}
